package com.czm.art_light.util;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.czm.art_light.constant.ArtErrorCodeEnum;
import com.czm.art_light.constant.CommonConsts;
import com.czm.art_light.constant.SystemConfigConsts;
import com.czm.art_light.exception.BusinessException;
import com.czm.art_light.param.response.RestResp;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import lombok.experimental.UtilityClass;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Objects;

@UtilityClass
@Slf4j
public class MinIoUtil {
    /**
     * 微信头像上传
     */
    public String uploadImage(String avatarUrl, String bucketName, MinioClient minioClient) {
        try {
            URL url = new URL(avatarUrl);
            InputStream inputStream = url.openStream();
            String saveFileName = IdWorker.get32UUID() + CommonConsts.WECHAT_AVATAR_FILE_DEFAULT_POSTFIX;
            LocalDateTime now = LocalDateTime.now();
            String savePath =
                    SystemConfigConsts.AVATAR_IMAGE_UPLOAD_DIRECTORY
                            + now.format(DateTimeFormatter.ofPattern("yyyy")) + CommonConsts.LINUX_FILE_PATH_PRE
                            + now.format(DateTimeFormatter.ofPattern("MM")) + CommonConsts.LINUX_FILE_PATH_PRE
                            + now.format(DateTimeFormatter.ofPattern("dd"));
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(savePath + CommonConsts.LINUX_FILE_PATH_PRE + saveFileName)
                    .stream(inputStream, -1, CommonConsts.WECHAT_AVATAR_FILE_LIMIT_SIZE)
                    .contentType(CommonConsts.WECHAT_AVATAR_FILE_DEFAULT_CONTENT_TYPE).build();
            //文件名称相同会覆盖
            minioClient.putObject(putObjectArgs);
            log.info("微信头像上传到minio成功,路径：{}",savePath + CommonConsts.LINUX_FILE_PATH_PRE + saveFileName);
            return savePath + CommonConsts.LINUX_FILE_PATH_PRE + saveFileName;
        } catch (IOException e) {
            // 上传的文件不是图片
            throw new BusinessException(ArtErrorCodeEnum.USER_UPLOAD_FILE_ERROR);
        } catch(BusinessException e) {
            // 上传的文件不是图片
            throw new BusinessException(e.getArtErrorCodeEnum());
        } catch (Exception e) {
            throw new BusinessException(ArtErrorCodeEnum.USER_UPLOAD_FILE_ERROR);
        }
    }

    /**
     * 文件上传
     */
    public RestResp<String> uploadImage(String imagePathPrefix,MultipartFile file, String bucketName, MinioClient minioClient) {
        try {
            if (Objects.isNull(ImageIO.read(file.getInputStream()))) {
                // 上传的文件不是图片
                throw new BusinessException(ArtErrorCodeEnum.USER_UPLOAD_FILE_ERROR);
            }
            String saveFileName = getSaveFileName(file);
            LocalDateTime now = LocalDateTime.now();
            String savePath =
                    imagePathPrefix
                            + now.format(DateTimeFormatter.ofPattern("yyyy")) + CommonConsts.LINUX_FILE_PATH_PRE
                            + now.format(DateTimeFormatter.ofPattern("MM")) + CommonConsts.LINUX_FILE_PATH_PRE
                            + now.format(DateTimeFormatter.ofPattern("dd"));
            PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(savePath + CommonConsts.LINUX_FILE_PATH_PRE + saveFileName)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            //文件名称相同会覆盖
            minioClient.putObject(putObjectArgs);
            return RestResp.ok(savePath + CommonConsts.LINUX_FILE_PATH_PRE + saveFileName);
        } catch (IOException e) {
            // 上传的文件不是图片
            throw new BusinessException(ArtErrorCodeEnum.USER_UPLOAD_FILE_ERROR);
        } catch(BusinessException e) {
            // 上传的文件不是图片
            throw new BusinessException(e.getArtErrorCodeEnum());
        } catch (Exception e) {
            throw new BusinessException(ArtErrorCodeEnum.USER_UPLOAD_FILE_ERROR);
        }
    }

    @NotNull
    private static String getSaveFileName(MultipartFile file) {
        String oriName = file.getOriginalFilename();
        assert oriName != null;
        //判断用户上传的是图片并且后缀名正确
        String nameSuffix = oriName.substring(oriName.lastIndexOf("."));
        if (!oriName.toLowerCase().endsWith(".jpg") &&!oriName.toLowerCase().endsWith(".png")
                && !oriName.toLowerCase().endsWith(".jpeg") && !oriName.toLowerCase().endsWith(".gif")
                && !oriName.toLowerCase().endsWith(".bpm")) {
            throw new BusinessException(ArtErrorCodeEnum.USER_UPLOAD_FILE_TYPE_NOT_MATCH);
        }
        //   /images/2024/03/18/c9d44f733aafd844.jpg
        return IdWorker.get32UUID() + nameSuffix;
    }

    /**
     * 删除 MinIO 上的文件
     *
     * @param bucketName 存储桶名称
     * @param imageUrl 文件路径（对象名）
     * @param minioClient MinIO 客户端实例
     */
    public static void deleteFile(String bucketName, String imageUrl, MinioClient minioClient) {
        try {
            log.info("开始删除 MinIO 文件，bucketName: {}, imageUrl: {}", bucketName, imageUrl);

            // 调用 MinIO 的删除对象方法
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(bucketName)
                            .object(imageUrl)
                            .build()
            );
            log.info("MinIO 文件删除成功，bucketName: {}, imageUrl: {}", bucketName, imageUrl);
        } catch (Exception e) {
            log.error("删除 MinIO 文件失败，bucketName: {}, imageUrl: {}, 错误信息: {}", bucketName, imageUrl, e.getMessage());
            //无需抛出异常
        }
    }
}
